package cs342.project1.mathNotebook.tests.xml;

import static org.junit.Assert.*;

import java.io.*;
import java.util.*;
import java.security.SecureRandom;

import org.junit.Before;
import org.junit.Test;

import cs342.project1.mathNotebook.xml.*;
import cs342.project1.mathNotebook.notebook.NotebookEntry;

/**
 * Tests the read/write functionality of the XML/Compression/DES Readers/Writers
 * @author Jared Schlicht
 * @author Gabrielle DuBois
 */
public class XMLTests {
	private final double delta = 0.001;
	private ByteArrayOutputStream outputStream;
	private List<NotebookEntry> defaultEntries;
	private NotebookEntry defaultEntry;
	private byte[] desKey;
	private SecureRandom secureRandom;

	/**
	 * Initializes the fresh in-memory collections
	 * @throws Exception
	 */
	@Before
	public void setUp() throws Exception {
		//initialize output stream
		this.outputStream = new ByteArrayOutputStream();

		//intialize default math notebook data structure
		defaultEntries = new ArrayList<NotebookEntry>();
		defaultEntry = new NotebookEntry();
		defaultEntry.functionString = "2x+3";
		defaultEntries.add(defaultEntry);

		//initialze DES key
		//create a secure random DES key--use SHA1PRNG
		//this would be passed to the DES encryptor
		desKey = new byte[32]; //256-bit
		secureRandom = SecureRandom.getInstance("SHA1PRNG");
		secureRandom.setSeed(secureRandom.generateSeed(20));
		secureRandom.nextBytes(desKey);
	}

	/**
	 * Verifies a basic xml file can be saved. Doesn't verify the contents.
	 */
	@Test
	public void testXMLSave() {
		NotebookWriter writer = new XMLWriter( new ByteArrayOutputStream() );
		boolean didSave = writer.saveFile( defaultEntries, new String("xmlFile") );

		assertTrue(didSave);
		/*
		//not working for some reason even though file does match....
		String result = this.outputStream.toString();

		assertEquals(
				"Must match expected output",
				"<?xml version=\"1.0\" ?><notebook><formula equation=\"2x+3\"></formula></notebook>",
				result);
		*/
	}

	/**
	 * Verifies a compressed file can be saved. Doesn't verify the contents.
	 */
	@Test
	public void testCommpressionSave() {
		NotebookWriter writer = new CompressionWriter( new ByteArrayOutputStream() );
		boolean didSave = writer.saveFile( defaultEntries, new String("xmlCompressedFile") );

		assertTrue(didSave);
	}

	/**
	 * Verifies an xml file can be loaded and that the contents is correct.
	 */
	@Test
	public void testXMLLoad() {
		NotebookReader reader = new XMLReader( new ByteArrayInputStream(new byte[1]) );
		List<NotebookEntry> defaultEntries2 = reader.loadFile( new String("xmlFile.xml") );

		assertTrue( defaultEntries.get(0).functionString.equals( defaultEntries2.get(0).functionString ) );
	}

	/**
	 * Verifies a file can be decompressed.
	 */
	@Test
	public void testCompressionLoad() {
		String fileName = "compressedFile2Decompress";
		String gzipFileName = "compressedFile2Decompress.gz";
		String finalFileName = "decompressedFile";
		//make compressed file
		NotebookWriter writer = new CompressionWriter( new ByteArrayOutputStream() );
		boolean didSave = writer.saveFile( defaultEntries, new String( fileName ) );
		assertTrue(didSave);

		NotebookReader reader = new CompressionReader( new ByteArrayInputStream(new byte[1]) );
		List<NotebookEntry> defaultEntries2 = reader.loadFile( gzipFileName );
		//System.out.println("Size of defaultEntries="+defaultEntries.size()+" Size of defaultEntries2="+defaultEntries2.size() );
		assertTrue( defaultEntries.get(0).functionString.equals( defaultEntries2.get(0).functionString ) );

		//Writing out file again for manual checking
		NotebookWriter writer2 = new XMLWriter( new ByteArrayOutputStream() );
		didSave = writer2.saveFile( defaultEntries2, new String("decompressedFile") );
		assertTrue(didSave);
	}

	/**
	 * Verifies an encrypted file can be saved. Doesn't verify the contents.
	 */
	@Test
	public void testDESSave() {
		NotebookWriter writer = new DESWriter( new ByteArrayOutputStream(), desKey );
		boolean didSave = writer.saveFile( defaultEntries, new String("xmlEncrytFile") );

		assertTrue(didSave);
	}

	/**
	 * Verifies an encrypted file can be loaded.
	 */
	@Test
	public void testDESLoad() {
		String fileName = "desFile2encrypt";
		String encrytedFileName = "desFile2encrypt.enc";
		//make encrypted file
		NotebookWriter writer = new DESWriter( new ByteArrayOutputStream(), desKey );
		boolean didSave = writer.saveFile( defaultEntries, new String(fileName) );
		assertTrue(didSave);

		NotebookReader reader = new DESReader( new ByteArrayInputStream(new byte[1]), desKey );
		List<NotebookEntry> defaultEntries2 = reader.loadFile( encrytedFileName );

		//System.out.println("testDESLoad(): Size of defaultEntries="+defaultEntries.size()+" Size of defaultEntries2="+defaultEntries2.size() );
		assertTrue( defaultEntries.get(0).functionString.equals( defaultEntries2.get(0).functionString ) );

		//Writing out file again for manual checking
		NotebookWriter writer2 = new XMLWriter( new ByteArrayOutputStream() );
		didSave = writer2.saveFile( defaultEntries2, new String("decryptedFile") );
		assertTrue(didSave);
	}

	/**
	 * Tests the reading of tangent points
	 */
/*	@Test
	public void testWriteTangents() {
		List<NotebookEntry> defaultEntries = new ArrayList<NotebookEntry>();
		NotebookEntry entry = new NotebookEntry();
		entry.functionString = "2x+3";
		entry.tangentPoints.add(4.5);
		entry.tangentPoints.add(-1.22);
		defaultEntries.add(entry);

		XMLNotebookWriter writer = new XMLNotebookWriter(this.outputStream);
		writer.writeAll(defaultEntries);

		String result = this.outputStream.toString();

		assertEquals(
				"Must match expected output",
				"<?xml version=\"1.0\" ?><notebook><formula equation=\"2x+3\"><tangent point=\"4.5\"></tangent><tangent point=\"-1.22\"></tangent></formula></notebook>",
				result);
	}
*/

	/**
	 * Tests the reading of tangent points
	 */
/*	@Test
	public void testReadTangents() {
		String expected = "<?xml version=\"1.0\" ?><notebook><formula equation=\"2x+3\"><tangent point=\"4.5\"></tangent><tangent point=\"-1.22\"></tangent></formula></notebook>";

		InputStream inputStream = new ByteArrayInputStream(expected.getBytes());
		NotebookReader reader = new XMLReader();

		List<NotebookEntry> defaultEntries = reader.loadStream(inputStream);
		assertTrue("The defaultEntries list must not be null", defaultEntries != null);
		assertTrue("There must be one entry in the notebook", defaultEntries.size() == 1);
		NotebookEntry entry = defaultEntries.get(0);

		assertTrue("There must be two tangent points in the entry", entry.tangentPoints.size() == 2);
		assertEquals("Tangent point 1 must be 4.5", 4.5, entry.tangentPoints.get(0), delta);
		assertEquals("Tangent point 2 must be -1.22", -1.22, entry.tangentPoints.get(1), delta);
	}
*/
}//XMLTests
